package com.eidos.blogs.openapi.utils;

import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.ReactiveHashOperations;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.time.Duration;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author ： Eidos
 * @date ：Created in 2020/12/28
 * @description：
 * @modified By：
 * @version: 1.0
 */
@Lazy
@Component
public class ReactiveRedisUtils {
    @Lazy
    @Resource(
            name = "reactiveRedisTemplate"
    )
    private ReactiveRedisTemplate<String, String> reactiveRedisTemplate;

    public ReactiveRedisUtils() {
    }

    public ReactiveRedisTemplate<String, String> getReactiveRedisTemplate() {
        return this.reactiveRedisTemplate;
    }

    public Mono<Boolean> set(String key, String val) {
        return this.set(this.getReactiveRedisTemplate(), key, val);
    }

    public Mono<Boolean> set(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, String val) {
        return reactiveRedisTemplate.opsForValue().set(key, val);
    }

    public Mono<Boolean> setIfAbsent(String key, String val) {
        return this.setIfAbsent(this.getReactiveRedisTemplate(), key, val);
    }

    public Mono<Boolean> setIfAbsent(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, String val) {
        return reactiveRedisTemplate.opsForValue().setIfAbsent(key, val);
    }

    public Mono<Boolean> setIfPresent(String key, String val) {
        return this.setIfPresent(this.getReactiveRedisTemplate(), key, val);
    }

    public Mono<Boolean> setIfPresent(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, String val) {
        return reactiveRedisTemplate.opsForValue().setIfPresent(key, val);
    }

    public Mono<Boolean> set(String key, String val, long expire) {
        return this.set(this.getReactiveRedisTemplate(), key, val, expire);
    }

    public Mono<Boolean> set(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, String val, long expire) {
        return reactiveRedisTemplate.opsForValue().set(key, val, Duration.ofSeconds(expire));
    }

    public Mono<Boolean> setIfAbsent(String key, String val, long expire) {
        return this.setIfAbsent(this.getReactiveRedisTemplate(), key, val, expire);
    }

    public Mono<Boolean> setIfAbsent(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, String val, long expire) {
        return reactiveRedisTemplate.opsForValue().setIfAbsent(key, val, Duration.ofSeconds(expire));
    }

    public Mono<Boolean> setIfPresent(String key, String val, long expire) {
        return this.setIfPresent(this.getReactiveRedisTemplate(), key, val, expire);
    }

    public Mono<Boolean> setIfPresent(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, String val, long expire) {
        return reactiveRedisTemplate.opsForValue().setIfPresent(key, val, Duration.ofSeconds(expire));
    }

    public Mono<Boolean> multiSet(Map<String, String> map) {
        return this.multiSet(this.getReactiveRedisTemplate(), map);
    }

    public Mono<Boolean> multiSet(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, Map<String, String> map) {
        return reactiveRedisTemplate.opsForValue().multiSet(map);
    }

    public Mono<Boolean> multiSetIfAbsent(Map<String, String> map) {
        return this.multiSetIfAbsent(this.getReactiveRedisTemplate(), map);
    }

    public Mono<Boolean> multiSetIfAbsent(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, Map<String, String> map) {
        return reactiveRedisTemplate.opsForValue().multiSetIfAbsent(map);
    }

    public Mono<Boolean> expire(String key, long expire) {
        return this.expire(this.getReactiveRedisTemplate(), key, expire);
    }

    public Mono<Boolean> expire(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, long expire) {
        return reactiveRedisTemplate.expire(key, Duration.ofSeconds(expire));
    }

    public Mono<Duration> getExpire(String key) {
        return this.getExpire(this.getReactiveRedisTemplate(), key);
    }

    public Mono<Duration> getExpire(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        return reactiveRedisTemplate.getExpire(key);
    }

    public Mono<String> get(String key) {
        return this.get(this.getReactiveRedisTemplate(), key);
    }

    public Mono<String> get(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        return reactiveRedisTemplate.opsForValue().get(key);
    }

    public Mono<String> getAndSet(String key, String value) {
        return this.getAndSet(this.getReactiveRedisTemplate(), key, value);
    }

    public Mono<String> getAndSet(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, String value) {
        return reactiveRedisTemplate.opsForValue().getAndSet(key, value);
    }

    public Mono<List<String>> multiGet(Collection<String> keys) {
        return this.multiGet(this.getReactiveRedisTemplate(), keys);
    }

    public Mono<List<String>> multiGet(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, Collection<String> keys) {
        return reactiveRedisTemplate.opsForValue().multiGet(keys);
    }

    public Flux<String> getkeys(String pattern) {
        return this.getkeys(this.getReactiveRedisTemplate(), pattern);
    }

    public Flux<String> getkeys(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String pattern) {
        return reactiveRedisTemplate.keys(pattern);
    }

    public Flux<String> getkeysByPrefix(String prefix) {
        return this.getkeysByPrefix(this.getReactiveRedisTemplate(), prefix);
    }

    public Flux<String> getkeysByPrefix(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String prefix) {
        return this.getkeys(reactiveRedisTemplate, prefix + "*");
    }

    public Mono<Long> delete(String... keys) {
        return this.delete(this.getReactiveRedisTemplate(), keys);
    }

    public Mono<Long> delete(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String... keys) {
        return reactiveRedisTemplate.delete(keys);
    }

    public Mono<Long> deleteByPrex(String prefix) {
        return this.deleteByPrex(this.getReactiveRedisTemplate(), prefix);
    }

    public Mono<Long> deleteByPrex(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String prefix) {
        return reactiveRedisTemplate.delete(this.getkeysByPrefix(prefix));
    }

    public Mono<Boolean> hasKey(String key) {
        return this.hasKey(this.getReactiveRedisTemplate(), key);
    }

    public Mono<Boolean> hasKey(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        return reactiveRedisTemplate.hasKey(key);
    }

    public Mono<Long> increment(String key) {
        return this.increment(this.getReactiveRedisTemplate(), key);
    }

    public Mono<Long> increment(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        return reactiveRedisTemplate.opsForValue().increment(key);
    }

    public Mono<Long> increment(String key, long delta) {
        return this.increment(this.getReactiveRedisTemplate(), key, delta);
    }

    public Mono<Long> increment(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, long delta) {
        return reactiveRedisTemplate.opsForValue().increment(key, delta);
    }

    public Mono<Long> decrement(String key) {
        return this.decrement(this.getReactiveRedisTemplate(), key);
    }

    public Mono<Long> decrement(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        return reactiveRedisTemplate.opsForValue().decrement(key);
    }

    public Mono<Long> decrement(String key, long delta) {
        return this.decrement(this.getReactiveRedisTemplate(), key, delta);
    }

    public Mono<Long> decrement(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, long delta) {
        return reactiveRedisTemplate.opsForValue().decrement(key, delta);
    }

    public <HK> Mono<Boolean> hput(String key, HK hashKey, String value) {
        return this.hput(this.getReactiveRedisTemplate(), key, hashKey, value);
    }

    public <HK> Mono<Boolean> hput(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, HK hashKey, String value) {
        return reactiveRedisTemplate.opsForHash().put(key, hashKey, value);
    }

    public <HK> Mono<String> hget(String key, HK hashKey) {
        return this.hget(this.getReactiveRedisTemplate(), key, hashKey);
    }

    public <HK> Mono<String> hget(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, HK hashKey) {
        ReactiveHashOperations<String, HK, String> ho = reactiveRedisTemplate.opsForHash();
        return ho.get(key, hashKey);
    }

    public <HK> Mono<List<String>> hmultiGet(String key, Collection<HK> hashKeys) {
        return this.hmultiGet(this.getReactiveRedisTemplate(), key, hashKeys);
    }

    public <HK> Mono<List<String>> hmultiGet(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, Collection<HK> hashKeys) {
        ReactiveHashOperations<String, HK, String> ho = reactiveRedisTemplate.opsForHash();
        return ho.multiGet(key, hashKeys);
    }

    public <HK> Mono<Boolean> hputAll(String key, Map<? extends HK, String> map) {
        return this.hputAll(this.getReactiveRedisTemplate(), key, map);
    }

    public <HK> Mono<Boolean> hputAll(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, Map<? extends HK, String> map) {
        return reactiveRedisTemplate.opsForHash().putAll(key, map);
    }

    public <HK> Mono<Boolean> hputIfAbsent(String key, HK hashKey, String value) {
        return this.hputIfAbsent(this.getReactiveRedisTemplate(), key, hashKey, value);
    }

    public <HK> Mono<Boolean> hputIfAbsent(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, HK hashKey, String value) {
        return reactiveRedisTemplate.opsForHash().putIfAbsent(key, hashKey, value);
    }

    public <HK> Flux<Map.Entry<HK, String>> enrtris(String key) {
        return this.enrtris(this.getReactiveRedisTemplate(), key);
    }

    public <HK> Flux<Map.Entry<HK, String>> enrtris(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        ReactiveHashOperations<String, HK, String> ho = reactiveRedisTemplate.opsForHash();
        return ho.entries(key);
    }

    public <HK> Mono<Boolean> hdelete(String key) {
        return this.hdelete(this.getReactiveRedisTemplate(), key);
    }

    public <HK> Mono<Boolean> hdelete(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        return reactiveRedisTemplate.opsForHash().delete(key);
    }

    public <HK> Mono<Long> hremove(String key, HK... hashKeys) {
        return this.hremove(this.getReactiveRedisTemplate(), key, hashKeys);
    }

    public <HK> Mono<Long> hremove(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, HK... hashKeys) {
        return reactiveRedisTemplate.opsForHash().remove(key, hashKeys);
    }

    public <HK> Mono<Boolean> hasKey(String key, HK hashKey) {
        return this.hasKey(this.getReactiveRedisTemplate(), key, hashKey);
    }

    public <HK> Mono<Boolean> hasKey(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, HK hashKey) {
        return reactiveRedisTemplate.opsForHash().hasKey(key, hashKey);
    }

    public <HK> Flux<HK> hkeys(String key) {
        return this.hkeys(this.getReactiveRedisTemplate(), key);
    }

    public <HK> Flux<HK> hkeys(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        ReactiveHashOperations<String, HK, String> ho = reactiveRedisTemplate.opsForHash();
        return ho.keys(key);
    }

    public <HK> Flux<String> hvalues(String key) {
        return this.hvalues(this.getReactiveRedisTemplate(), key);
    }

    public <HK> Flux<String> hvalues(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        ReactiveHashOperations<String, HK, String> ho = reactiveRedisTemplate.opsForHash();
        return ho.values(key);
    }

    public <HK> Mono<Long> hincrement(String key, HK hashKey, long delta) {
        return this.hincrement(this.getReactiveRedisTemplate(), key, hashKey, delta);
    }

    public <HK> Mono<Long> hincrement(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, HK hashKey, long delta) {
        return reactiveRedisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    public <HK> Mono<Double> hincrement(String key, HK hashKey, double delta) {
        return this.hincrement(this.getReactiveRedisTemplate(), key, hashKey, delta);
    }

    public <HK> Mono<Double> hincrement(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, HK hashKey, double delta) {
        return reactiveRedisTemplate.opsForHash().increment(key, hashKey, delta);
    }

    public Mono<Long> hsize(String key) {
        return this.hsize(this.getReactiveRedisTemplate(), key);
    }

    public Mono<Long> hsize(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        return reactiveRedisTemplate.opsForHash().size(key);
    }

    public Mono<Boolean> renameKey(String oldKey, String newKey) {
        return this.renameKey(this.getReactiveRedisTemplate(), oldKey, newKey);
    }

    public Flux<String> members(String key) {
        return this.members(this.getReactiveRedisTemplate(), key);
    }

    public Flux<String> members(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key) {
        return reactiveRedisTemplate.opsForSet().members(key);
    }

    public Mono<Long> addSet(String key, String... values) {
        return this.addSet(this.getReactiveRedisTemplate(), key, values);
    }

    public Mono<Long> addSet(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, String... values) {
        return reactiveRedisTemplate.opsForSet().add(key, values);
    }

    public Mono<Long> removeSet(String key, String... values) {
        return this.removeSet(this.getReactiveRedisTemplate(), key, values);
    }

    public Mono<Long> removeSet(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String key, String... values) {
        return reactiveRedisTemplate.opsForSet().remove(key, values);
    }

    public Mono<Boolean> renameKey(ReactiveRedisTemplate<String, String> reactiveRedisTemplate, String oldKey, String newKey) {
        return reactiveRedisTemplate.rename(oldKey, newKey);
    }

    public Flux<String> ping() {
        return this.ping(this.getReactiveRedisTemplate());
    }

    public Flux<String> ping(ReactiveRedisTemplate<String, String> reactiveRedisTemplate) {
        return reactiveRedisTemplate.execute((connection) -> {
            return connection.ping();
        });
    }
}
